/** 自定义的UI类,需要配合MyMacro类的子类使用
  生成一个界面,指定WIN_TITLE,游戏按键设置,热键设置,动态变更热键对应的宏
  并支持设定预设菜单与自定义新的gui组件到自定义页面(需要在子类重载方法_customGui())

  By setycyas @2023-02-06
*/

#Include "..\Class\MyEmu.2.ahk"

class MyUI {

  /* 常量
  */
  DEFAULT_GAME_KEYS := "x,e" ;默认的游戏按键
  HOTKEY_NUM := 7 ;热键数量
  DEFAULT_HOTKEYS := "w,q,2,3,r,a,f" ;默认的热键,数量与HOTKEY_NUM相同,可小于该数值但不能大于

  /* 私有变量
  */
  _title := "" ;标题
  _macro := "" ;MyMacro类的子类对象,用于设定热键与宏的对于
  _submitTimes := 0 ;数据提交次数,主要用于判断是否首次提交
  _winTitle := "" ;绑定热键时对应的winTitle
  _hotkeys := [] ;热键表
  _preset := "" ;预设表,用于预设菜单

  ;**Gui组件相关
  _myGui := "" ;Gui窗口对象
  _tab := "" ;标签页对象
  _exeComboBox := "" ;选择exe的comboBox对象
  _gameKeyEdit := "" ;指定游戏按键的文本输入框
  _hotkeyEdit := "" ;指定热键的文本输入框,用不完的热键可以留空
  _hotkeyTexts := [] ;显示热键名称的文字组件[]
  _macroComboBoxes := [] ;选择宏的comboBox组件[]
  _submitButton := "" ;提交按钮
  _menuBar := "" ;菜单栏
  _statusBar := "" ;状态栏

  /* 构造函数,title是标题字符串,macro是MyMacro类或子类,preset是一个宏预设Map,可留空
  */
  __New(title, macro, preset := ""){
    this._title := title
    this._macro := macro
    this._preset := preset
  }

  /* 公有函数
  */
  ;** 设置界面,使用的主要函数
  setup(){
    local i, k, v ;循环用临时变量
    local presetMenu ;预设菜单临时变量
    this._myGui := Gui("", this._title)
    this._myGui.onEvent("close", this._onGuiClose.bind(this))
    this._tab := this._myGui.Add("Tab3",, ["初始设定", "宏设置", "自定义"])
    ;初始设定标签页
    this._tab.UseTab(1)
    this._myGui.Add("Text", "x+20 y+20 w100", "选择exe:")
    this._exeComboBox := this._myGui.Add("ComboBox", "xp+80 yp-3 w100 choose1",
      [MyEmu.NEBULA, MyEmu.WINKAWAKS, MyEmu.XZONE])
    this._myGui.Add("Text", "xp-80 yp+40 w100", "设定游戏按键:")
    this._gameKeyEdit := this._myGui.Add("Edit", "xp+80 yp-3 w100", this.DEFAULT_GAME_KEYS)
    this._myGui.Add("Text", "xp-80 yp+40 w100", "设定" . this.HOTKEY_NUM . "个热键:")
    this._hotkeyEdit := this._myGui.Add("Edit", "xp+80 yp-3 w100", this.DEFAULT_HOTKEYS)
    ;宏设置标签页
    this._tab.UseTab(2)
    loop this.HOTKEY_NUM {
      if (A_Index == 1){
        this._hotkeyTexts.push(this._myGui.Add("Text", "x+20 y+20 w40", "热键1:"))
      } else {
        this._hotkeyTexts.push(this._myGui.Add("Text", "xp-60 yp+30 w40", "热键" . A_Index . ":"))
      }
      this._macroComboBoxes.push(this._myGui.Add("ComboBox", "xp+60 yp-3 choose1", this._macro.macroArr))
    }
    ;自定义标签页,需要在子类重写customGui()方法实现
    this._tab.UseTab(3)
    this._customGui()
    this._tab.UseTab()
    ;添加预设菜单
    if (this._preset != ""){
      this._menuBar := MenuBar()
      presetMenu := Menu()
      for k, v in this._preset {
        presetMenu.Add(k, this.readPresetMenu.bind(this))
      }
      this._menuBar.Add("读取预设", presetMenu)
      this._myGui.MenuBar := this._menuBar
    }
    ;提交数据按钮与显示
    this._submitButton := this._myGui.Add("Button", , "提交")
    this._submitButton.OnEvent("Click", this._onSubmitButton.bind(this))
    ;状态栏
    this._statusBar := this._myGui.Add("StatusBar",, "状态栏")
    ;显示
    this._myGui.show()
  }

  ;** 提交数据,外部可调用
  submit(){
    if (this._submitTimes < 1){
      this._onFirstSubmit()
    }
    this._setHotkeys()
    this._onSubmitEnd()
    this._submitTimes += 1
  }

  /* 界面事件响应
  */
  _onSubmitButton(btnObj, info){
    this.submit()
    MsgBox("提交数据成功")
  }

  _onGuiClose(thisGui){
    ExitApp()
  }

  ;外部可调用,读取预设
  readPresetMenu(itemName, itemPos := "", _menu := ""){
    this._tab.Choose(2)
    loop this._preset[itemName].Length {
      if (!this._macroComboBoxes[A_Index].Enabled){
        break
      } else {
        this._macroComboBoxes[A_Index].choose(this._preset[itemName][A_Index])
      }
    }
    this._statusBar.SetText("读入预设" . itemName)
  }

  /* 私有函数
  */
  ;** 绑定热键
  _setHotkeys(){
    local keyName, macroName
    HotIfWinActive(this._winTitle)
    loop this._hotkeys.Length {
      keyName := this._hotkeys[A_Index]
      macroName := this._macroComboBoxes[A_Index].Text
      if ((keyName != "") and (this._macro.macroMap.Has(macroName))){
        Hotkey(keyName, this._macro.macroMap[macroName])
      }
    }
    HotIfWinActive()
  }

  ;**首次提交数据时的处理
  _onFirstSubmit(){
    local gameKeys
    ;禁用所有只能提交一次的项目
    this._exeComboBox.Opt("+Disabled")
    this._gameKeyEdit.Opt("+Disabled")
    this._hotkeyEdit.Opt("+Disabled")
    ;首次提交的数据处理,记录exe和游戏按键,热键,留空的热键将被设定为无效
    this._winTitle := "ahk_exe " . this._exeComboBox.Text
    gameKeys := StrSplit(this._gameKeyEdit.Text, ",")
    this._macro.refreshKeys(gameKeys)
    this._hotkeys := StrSplit(this._hotkeyEdit.Text, ",")
    loop this.HOTKEY_NUM {
      if ((this._hotkeys.Has(A_Index)) and (this._hotkeys[A_Index] != "")){
        this._hotkeyTexts[A_Index].Text := "热键" . this._hotkeys[A_Index] . ":"
      } else {
        this._hotkeyTexts[A_Index].Text := "无效键"
        this._macroComboBoxes[A_Index].Opt("+Disabled")
      }
    }
  }

  /* 需要在子类重写的接口
  */
  ;自定义gui组件标签页
  _customGui(){
  }
  ;提交数据后的后续处理
  _onSubmitEnd(){
  }

}

